package microcredit.model;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.OrderBy;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import microcredit.model.base.Model;
import microcredit.model.domain.Status;
import microcredit.model.util.ModelUtils;

/**
 * Entity implementation class for Entity: Group Represents a group for members.
 * A member can be assigned to multiple groups and a group can have multiple
 * members. Normally this represents a real life group of people which are
 * working together and responsible for each other.
 * 
 * @author Christian Humer
 * @since 1.0
 */
@Entity
public class MemberGroup extends Model implements Serializable {

	private static final long serialVersionUID = 1L;

	public static final String SHORT_NAME= "shortName";
	public static final String NAME= "name";
	public static final String TRESURER_MEMBER= "tresurerMember";
	public static final String SECRETARY_MEMBER= "secretaryMember";
	public static final String CHAIRMAN_MEMBER= "chairmanMember";
	
	
	
	public MemberGroup() {
		super();
	}

	/**
	 * The unique id of this member group.
	 */
	@Id
	@GeneratedValue(strategy = GenerationType.SEQUENCE)
	private Long id;

	/**
	 * A short name of the member group.
	 */
	@OrderBy
	private String shortName;

	/**
	 * The full name of the member group.
	 */
	private String name;

	/**
	 * The member that is responsible for finance.
	 */
	@OneToOne
	private Member tresurerMember;

	/**
	 * The member that is responsible for secretary.
	 */
	@OneToOne
	private Member secretaryMember;

	/**
	 * The member that is responsible for leading the group.
	 */
	@OneToOne
	private Member chairmanMember;

	/**
	 * Additional general description of the group. For example meetings etc.
	 */
	@Column(length = 500)
	private String meetingsText;

	/**
	 * The status of the member group. A for active I for inactive.
	 */
	@Enumerated(EnumType.STRING)
	@Column(length = 1)
	private Status status;

	/**
	 * The time this entity was inserted.
	 */
	@Temporal(TemporalType.TIMESTAMP)
	@Column(nullable = false)
	private Date insertStamp;

	/**
	 * The time this entity was last updated.
	 */
	@Temporal(TemporalType.TIMESTAMP)
	@Column(nullable = false)
	private Date updateStamp;

	/**
	 * Validations before the entity is persisted to database.
	 * 
	 * @throws ValidationException
	 */
	@PrePersist
	public void prePersist() throws ValidationException {
		if (getInsertStamp() == null) {
			setInsertStamp(ModelUtils.createTimestamp());
		}
		setUpdateStamp(getInsertStamp());
		setStatus(Status.A);
		validate();
	}

	/**
	 * Better implementation of hashCode. Utilizes the id as hashcode.
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}

	/**
	 * Compares two entities using ids.
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		MemberGroup other = (MemberGroup) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		return true;
	}

	/**
	 * Will be called before the entity is updates. Updates the updateStamp.
	 * 
	 * @throws ValidationException
	 */
	@PreUpdate
	public void preUpdate() throws ValidationException {
		setUpdateStamp(ModelUtils.createTimestamp());
		validate();
	}

	/**
	 * Returns a concatination of firstName .middleName and lastName.
	 */
	public String getFullName() {
		StringBuilder builder = new StringBuilder();
		if (getShortName() != null) {
			builder.append(getShortName());
			if (getName() != null) {
				builder.append(" - ");
			}
		}
		if (getName() != null) {
			builder.append(getName());
		}
		return builder.toString();
	}

	public void validate() throws ValidationException {
		// currently no direct entity validations
	}

	// getters and setters see field description

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		Object oldid = this.id;
		this.id = id;
		firePropertyChange("id", oldid, this.id);
	}

	public String getShortName() {
		return shortName;
	}

	public void setShortName(String shortName) {
		Object oldshortName = this.shortName;
		this.shortName = shortName;
		firePropertyChange("shortName", oldshortName, this.shortName);
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		Object oldname = this.name;
		this.name = name;
		firePropertyChange("name", oldname, this.name);
	}

	public Member getTresurerMember() {
		return tresurerMember;
	}

	public void setTresurerMember(Member tresurerMember) {
		Object oldtresurerMember = this.tresurerMember;
		this.tresurerMember = tresurerMember;
		firePropertyChange("tresurerMember", oldtresurerMember,
				this.tresurerMember);
	}

	public Member getSecretaryMember() {
		return secretaryMember;
	}

	public void setSecretaryMember(Member secretaryMember) {
		Object oldsecretaryMember = this.secretaryMember;
		this.secretaryMember = secretaryMember;
		firePropertyChange("secretaryMember", oldsecretaryMember,
				this.secretaryMember);
	}

	public Member getChairmanMember() {
		return chairmanMember;
	}

	public void setChairmanMember(Member chairmanMember) {
		Object oldchairmanMember = this.chairmanMember;
		this.chairmanMember = chairmanMember;
		firePropertyChange("chairmanMember", oldchairmanMember,
				this.chairmanMember);
	}

	public String getMeetingsText() {
		return meetingsText;
	}

	public void setMeetingsText(String meetingsText) {
		Object oldmeetingsText = this.meetingsText;
		this.meetingsText = meetingsText;
		firePropertyChange("meetingsText", oldmeetingsText, this.meetingsText);
	}

	public Status getStatus() {
		return status;
	}

	public void setStatus(Status status) {
		Object oldstatus = this.status;
		this.status = status;
		firePropertyChange("status", oldstatus, this.status);
	}

	public Date getInsertStamp() {
		return insertStamp;
	}

	public void setInsertStamp(Date insertStamp) {
		Object oldinsertStamp = this.insertStamp;
		this.insertStamp = insertStamp;
		firePropertyChange("insertStamp", oldinsertStamp, this.insertStamp);
	}

	public Date getUpdateStamp() {
		return updateStamp;
	}

	public void setUpdateStamp(Date updateStamp) {
		Object oldupdateStamp = this.updateStamp;
		this.updateStamp = updateStamp;
		firePropertyChange("updateStamp", oldupdateStamp, this.updateStamp);
	}
	
	@Override
	public String toString() {
		if (shortName != null) {
			return "Member group ["+shortName+"]";
		} else {
			return "Member group ";
		}
	}

}
